home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / lang / sbasic02 / exparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-04  |  5.3 KB  |  335 lines

  1. /**********************************************************/
  2. /* Recursive descent parser (exparse.c) V0.1          */
  3. /* Copyright (C) 1994 James J. Bielman             */
  4. /* Adapted from _C Power User's Guide_ by Herbert Schildt */
  5. /**********************************************************/
  6. #include<setjmp.h>
  7. #include<math.h>
  8. #include<ctype.h>
  9. #include<stdlib.h>
  10. #include<stdio.h>
  11.  
  12. #define DELIMITER    1
  13. #define VARIABLE    2
  14. #define NUMBER        3
  15. #define COMMAND        4
  16. #define STRING        5
  17. #define QUOTE        6
  18.  
  19. #define EOL        9
  20. #define FINISHED    10
  21.  
  22. extern char *prog;    /* Expression to be analyzed */
  23. extern jmp_buf e_buf;
  24. extern int variables[26];
  25. extern int source_line;
  26.  
  27. extern struct commands {
  28.     char command[20];
  29.     char tok;
  30. } table[];
  31.  
  32. extern char token[];    /* Holds string represtation of token */
  33. extern char token_type;
  34. extern char tok;
  35.  
  36. void get_exp(int *result);
  37. void level2(int *result);
  38. void level3(int *result);
  39. void level4(int *result);
  40. void level5(int *result);
  41. void level6(int *result);
  42. void primitive(int *result);
  43. void arith(char o, int *r, int *h);
  44. void unary(char o, int *r);
  45. void serror(int error); 
  46. void putback();
  47. int  get_token();
  48. int  look_up(char *s);
  49. int  isdelim(char c);
  50. int  iswhite(char c);
  51. int  find_var(char *s);
  52.  
  53. /* Main entry point into parser */
  54. void get_exp(int *result)
  55. {
  56.     get_token();
  57.  
  58.     if(!*token)
  59.     {
  60.         serror(2);
  61.         return;
  62.     }
  63.     level2(result);
  64.     putback();
  65. }
  66.  
  67. /* +- */
  68. void level2(int *result)
  69. {
  70.     register char op;
  71.     int hold;
  72.  
  73.     level3(result);
  74.     while((op = *token) == '+' || op == '-')
  75.     {
  76.         get_token();
  77.         level3(&hold);
  78.         arith(op, result, &hold);
  79.     }
  80. }
  81.  
  82. /* /%* */
  83. void level3(int *result)
  84. {
  85.     register char op;
  86.     int hold;
  87.  
  88.     level4(result);
  89.     while((op = *token) == '*' || op == '/' || op == '%')
  90.     {
  91.         get_token();
  92.         level4(&hold);
  93.         arith(op, result, &hold);
  94.     }
  95. }
  96.  
  97. void level4(int *result)
  98. {
  99.     int hold;
  100.  
  101.     level5(result);
  102.     while(*token == '^')
  103.     {
  104.         get_token();
  105.         level4(&hold);
  106.         arith('^', result, &hold);
  107.     }
  108. }
  109.  
  110. void level5(int *result)
  111. {
  112.     register char op;
  113.  
  114.     op = 0;
  115.     if((token_type == DELIMITER) && *token == '+' || *token == '-')
  116.     {
  117.         op = *token;
  118.         get_token();
  119.     }
  120.     level6(result);
  121.     if(op) unary(op, result);
  122. }
  123.  
  124. void level6(int *result)
  125. {
  126.     if((*token == '(') && (token_type == DELIMITER))
  127.     {
  128.         get_token();
  129.         level2(result);
  130.         if(*token != ')')
  131.             serror(1);
  132.         get_token();
  133.     }
  134.     else primitive(result);
  135. }
  136.  
  137. void primitive(int *result)
  138. {
  139.     switch(token_type)
  140.     {
  141.         case VARIABLE:
  142.             *result = find_var(token);
  143.             get_token();
  144.             return;
  145.  
  146.         case NUMBER:
  147.             *result = atoi(token);
  148.             get_token();
  149.             return;
  150.  
  151.         default:
  152.             serror(0);
  153.     }
  154. }
  155.  
  156. void arith(char o, int *r, int *h)
  157. {
  158.     register int t, ex;
  159.  
  160.     switch(o)
  161.     {
  162.         case '-':
  163.             *r = *r - *h;
  164.             break;
  165.  
  166.         case '+':
  167.             *r = *r + *h;
  168.             break;
  169.  
  170.         case '*':
  171.             *r = *r * *h;
  172.             break;
  173.  
  174.         case '/':
  175.             *r = (*r) / (*h);
  176.             break;
  177.  
  178.         case '%':
  179.             t = (*r) / (*h);
  180.             *r = *r - (t * (*h));
  181.             break;
  182.  
  183.         case '^':
  184.             ex = *r;
  185.             if(*h == 0)
  186.             {
  187.                 *r = 1;
  188.                 break;
  189.             }
  190.             for(t = *h-1; t > 0; --t) *r = (*r) * ex;
  191.             break;
  192.     }
  193. }
  194.  
  195. void unary(char o, int *r)
  196. {
  197.     if(o == '-') *r = -(*r);
  198. }
  199.  
  200. int find_var(char *s)
  201. {
  202.     if(!isalpha(*s))
  203.     {
  204.         serror(4);
  205.         return 0;
  206.     }
  207.     return variables[toupper(*token) - 'A'];
  208. }
  209.  
  210. void serror(int error)
  211. {
  212.     static char *e[] = {
  213.         "Syntax error",
  214.         "Unbalanced parens",
  215.         "No expression present",
  216.         "Expected: =",
  217.         "Not a variable",
  218.         "Lable table full",
  219.         "Duplicate label",
  220.         "Undefined label",
  221.         "Expected: THEN",
  222.         "Expected: TO",
  223.         "Too many nested FOR loops",
  224.         "NEXT without FOR",
  225.         "Too many nested GOSUBs",
  226.         "RETURN without GOSUB"
  227.     };
  228.  
  229.     printf("Line %d: %s\n", source_line, e[error]);
  230.     longjmp(e_buf, 1);
  231. }
  232.  
  233. int get_token()
  234. {
  235.     register char *temp;
  236.  
  237.     token_type = tok = 0;
  238.     temp = token;
  239.     if(*prog == EOF)
  240.     {
  241.         *token = 0;
  242.         tok = FINISHED;
  243.         return(token_type = DELIMITER);
  244.     }
  245.  
  246.     while(iswhite(*prog)) prog++;
  247.  
  248.     if(*prog == '\n')
  249.     {
  250.         prog++;
  251.         source_line++;
  252.         tok = EOL;
  253.         *token = '\n';
  254.         token[1] = 0;
  255.         return(token_type = DELIMITER);
  256.     }
  257.  
  258.     if(strchr("+-*^/%=;(),<>", *prog))
  259.     {
  260.         *temp = *prog;
  261.         prog++;
  262.         temp++;
  263.         *temp = 0;
  264.         return(token_type = DELIMITER);
  265.     }
  266.  
  267.     if(*prog == '"')
  268.     {
  269.         prog++;
  270.         while(*prog != '"' && *prog != '\r') *temp++ = *prog++;
  271.         if(*prog == '\n') serror(1);
  272.         prog++;
  273.         *temp = 0;
  274.         return(token_type = QUOTE);
  275.     }
  276.  
  277.     if(isdigit(*prog))
  278.     {
  279.         while(!isdelim(*prog)) *temp++ = *prog++;
  280.         *temp = 0;
  281.         return(token_type = NUMBER);
  282.     }
  283.  
  284.     if(isalpha(*prog))
  285.     {
  286.         while(!isdelim(*prog)) *temp++ = *prog++;
  287.         token_type = STRING;
  288.     }
  289.  
  290.     *temp = '\0';
  291.  
  292.     if(token_type == STRING)
  293.     {
  294.         tok = look_up(token);
  295.         if(!tok) token_type = VARIABLE;
  296.         else token_type = COMMAND;
  297.     }
  298.     return token_type;
  299. }
  300.  
  301. void putback()
  302. {
  303.     char *t;
  304.  
  305.     if(tok == EOL) source_line--;
  306.  
  307.     t = token;
  308.     for(; *t; t++) prog--;
  309. }
  310.  
  311. int look_up(char *s)
  312. {
  313.     register i, j;
  314.     char *p;
  315.  
  316.     p = s;
  317.     while(*p) { *p = tolower(*p); p++; }
  318.     for(i = 0; *table[i].command; i++)
  319.         if(!strcmp(table[i].command, s)) return table[i].tok;
  320.     return 0;
  321. }
  322.  
  323. int isdelim(char c)
  324. {
  325.     if(strchr(" ;,+-<>/*%^=()", c) || c == 9 || c == '\n' || c == 0)
  326.         return 1;
  327.     return 0;
  328. }
  329.  
  330. int iswhite(char c)
  331. {
  332.     if(c == ' ' || c == '\t') return 1;
  333.     else return 0;
  334. }
  335.